package com.feibiao.computerUI;
import com.feibiao.computer.OperatorFactory;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MyCalucatorUI extends JFrame implements ActionListener {
    private JTextField tf;//计算器上方的文本框
    private JPanel panel;//定义面板
    private JMenuBar myBar;//定义菜单条
    private JMenu menul, menu2, menu3;//定义菜单
    private JMenuItem editItem1, editItem2, help1, help2;//定义菜单项
    private JRadioButtonMenuItem seeItem1, seeItem2;//定义单选按钮菜单项
    //定义一个按钮组，意味着开启其中一个按钮时，将关闭组中的其他所有按钮
    private ButtonGroup bg;
    private boolean firstNum = true;//判断是否为第一个运算数
    private String operator = "=";//初始化运算符
    private double result = 0.0;//初始化计算结果
    public MyCalucatorUI() {
        //父类JFrame的构造方法，用于显示标题
        super("计算器-李飞彪");
        //设置总体布局为边界式布局，组件之间宽高间隔为10px
        this.setLayout(new BorderLayout(10, 10));
        //定义一个面板，采用6行8列的网格式布局
        panel = new JPanel(new GridLayout(6, 8, 7, 7));
        /*
         *以下注释掉的代码是定义模仿Windows7计算器的菜单，只写出了界面但是没有实现功能
         * 可以不实现
         * */
        myBar = new JMenuBar();
        menul = new JMenu("查看(V)");
        menu2 = new JMenu("编辑(E)");
        menu3 = new JMenu("帮助(H)");
        menul.setFont(new Font("", Font.PLAIN, 13));
        menu2.setFont(new Font("", Font.PLAIN, 13));
        menu3.setFont(new Font("", Font.PLAIN, 13));
        seeItem1 = new JRadioButtonMenuItem("科学型(T)");
        seeItem2 = new JRadioButtonMenuItem("标准型(S)");
        seeItem1.setFont(new Font("", Font.PLAIN, 13));
        seeItem2.setFont(new Font("", Font.PLAIN, 13));
        editItem1 = new JMenuItem("复制(C)");
        editItem2 = new JMenuItem("粘贴(P)");
        editItem1.setFont(new Font("", Font.PLAIN, 13));
        editItem2.setFont(new Font("", Font.PLAIN, 13));
        help1 = new JMenuItem("查看帮助(V)");
        help2 = new JMenuItem("关于计算器(A)");
        help1.setFont(new Font("", Font.PLAIN, 13));
        help2.setFont(new Font("", Font.PLAIN, 13));
        bg = new ButtonGroup();
        bg.add(seeItem1);
        bg.add(seeItem2);
        menul.add(seeItem1);
        menul.addSeparator();
        menul.add(seeItem2);
        menu2.add(editItem1);
        menu2.addSeparator();
        menu2.add(editItem2);
        menu3.add(help1);
        menu3.addSeparator();
        menu3.add(help2);
        myBar.add(menul);
        myBar.add(menu2);
        myBar.add(menu3);
        this.setJMenuBar(myBar);
        tf = new JTextField();//定义文本框,显示输入的数据
        tf.setFont(new Font("宋体", Font.BOLD, 40));//设置文本框字体
        tf.setEditable(false);//设置文本框不能被编辑
        tf.setBorder(BorderFactory.createLineBorder(Color.black, 2));//设置文本框的边界样式
        tf.setText("0");//设置文本框的默认值为0
        tf.setBackground(Color.white);//设置文本框的背景颜色
        tf.setHorizontalAlignment(JTextField.RIGHT);//设置文本框的文本对齐为右对齐
        init();//调用初始化界面方法

    }
    //初始化界面方法init（）
    public void init() {
        /*以下代码为向面板中添加按钮,设置按钮名称,文字颜色和字号,使用的是后面定义白 addButton()方法。*/
        addButton(panel, "o", Color.magenta, 20);
        addButton(panel, "n!", Color.magenta, 20);
        addButton(panel, "In", Color.magenta, 20);
        addButton(panel, "MC", Color.blue, 15);
        addButton(panel, "MR", Color.blue, 15);
        addButton(panel, "MS", Color.blue, 15);
        addButton(panel, "M+", Color.blue, 15);
        addButton(panel, "M-", Color.blue, 15);
        addButton(panel, "y√x", Color.magenta, 17);
        addButton(panel, "x^y", Color.magenta, 17);
        addButton(panel, "sin", Color.magenta, 20);
        addButton(panel, "←", Color.green, 20);
        addButton(panel, "CE", Color.green, 18);
        addButton(panel, "C", Color.green, 20);
        addButton(panel, "±", Color.magenta, 25);
        addButton(panel, "√", Color.magenta, 23);
        addButton(panel, "3√x", Color.magenta, 16);
        addButton(panel, "x^3", Color.magenta, 16);
        addButton(panel, "cos", Color.magenta, 18);
        addButton(panel, "7", Color.black, 25);
        addButton(panel, "8", Color.black, 25);
        addButton(panel, "9", Color.black, 25);
        addButton(panel, "/", Color.red, 25);
        addButton(panel, "%", Color.magenta, 20);
        addButton(panel, "Int", Color.magenta, 18);
        addButton(panel, "x^2", Color.magenta, 16);
        addButton(panel, "tan", Color.magenta, 19);
        addButton(panel, "4", Color.black, 25);
        addButton(panel, "5", Color.black, 25);
        addButton(panel, "6", Color.black, 25);
        addButton(panel, "*", Color.red, 25);
        addButton(panel, "1/x", Color.magenta, 20);
        addButton(panel, "Exp", Color.magenta, 15);
        addButton(panel, "sinh", Color.magenta, 13);
        addButton(panel, "log", Color.magenta, 20);
        addButton(panel, "1", Color.black, 25);
        addButton(panel, "2", Color.black, 25);
        addButton(panel, "3", Color.black, 25);
        addButton(panel, "-", Color.red, 25);
        addButton(panel, "e", Color.magenta, 25);
        addButton(panel, "Mod", Color.magenta, 14);
        addButton(panel, "cosh", Color.magenta, 13);
        addButton(panel, "10^x", Color.magenta, 12);
        addButton(panel, "0", Color.black, 25);
        addButton(panel, "π", Color.magenta, 25);
        addButton(panel, ".", Color.black, 25);
        addButton(panel, "+", Color.red, 25);
        addButton(panel, "=", Color.BLACK, 25);
        //总体采用的是边界式布局,将文本框定义在北部
        this.add(tf, BorderLayout.NORTH);
        //向布局中添加面板组件
        this.add(panel);
        // 将所有组件都设置为适合大小
        this.pack();
        //设置计算器界面的大小为540x320
        this.setSize(540, 320);
        //设置界面在屏幕中出现的位置
        this.setLocation(450, 150);
        //设置界面的大小不可调整
        this.setResizable(false);
        //设置对话框的关闭事件
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    public void addButton(JPanel panel, String name, Color color, int a) {
        //传入参数为按钮所在的面板,按钮的名称,按钮的前景色和字号
        JButton jbt = new JButton(name);//添加新按钮
        jbt.setFont(new Font("Times New Roman", Font.BOLD, a));//设置按钮的字体样式
        panel.add(jbt);//向面板中添加此按钮
        jbt.setForeground(color);//设置前景色
        // /*MC,MR, MS、 M+、M-按钮的功能未实现,为除了这5个按钮的所有按钮添加监听事件*/
        if (name == "MC" || name == "MR" || name == "MS" | name == "M+" || name == "M-") {
            jbt.addActionListener(null);
        } else {
            jbt.addActionListener(this);
        }
    }
    public void actionPerformed(ActionEvent e) {
        //得到与按键相关的命令字符串，赋值给key.key就是输入的运算数或运算符
        String key = e.getActionCommand();
        //利用index()方法判断,如果输入的是0123456789或1或e按钮,则执行setNum0方法
        //如果不是纯数字，则开始进行如下判断
        if ("0123456789πe".indexOf(key) >= 0) {
            this.setNum(key);
        }else switch (key) {
            case "."://输入的是“.”执行setDot()方法
                this.setDot();
                break;
            case "C"://输入的是“C”或“CE”，执行setC()方法
                this.setC();
                break;
            case "CE"://输入的是“C”或“CE”，执行setC()方法
                this.setC();
                break;
            case "←"://输入的是"←"，执行setBacksqace()方法
                this.setBackspace();
                break;
            //如果不是以上命令，则输入的一定是操作符按钮
            default:
                try {
                    if ("+-*/=Modx^y".indexOf(key) >= 0 || key.equals("y√x")){
                        this.result = OperatorFactory.getOperatorInstance(this.operator).compute(this.getNumber(),this.result);
                        //在文本框中打印结果，结果需要转换为String类型。changeNum（）是本类中定义的方法，目的是把double转换为String型*/
                        this.tf.setText(changeNum(this.result));
                        //将用户输入的key赋给operator成员变量
                        this.operator = key;
                        this.firstNum = true;
                    }else{
                        this.operator = key;
                        this.result = OperatorFactory.getOperatorInstance(this.operator).compute(this.getNumber());
                        this.tf.setText(changeNum(this.result));
                        //初始化成员变量
                        this.firstNum = true;
                    }
                } catch (Exception e1) {
                    this.tf.setText(e1.getMessage());
                }
                break;
        }
    }
    public void setNum(String key){
        if (this.firstNum) {
            //如果是第一个运算数
            this.tf.setText("");//设置文本框为“”
            this.firstNum = false;//改为不是第一个运算数,再输入数字时跳过这个if
        }
        if (key == "π") {
            //直接在文本框中输出π
            this.tf.setText(String.valueOf(Math.PI));
            this.firstNum = true;
        } else if (key == "e") {
            //直接在文本框中输出e
            this.tf.setText(String.valueOf(Math.E));
            this.firstNum = true;
        } else {
            this.tf.setText(this.tf.getText().trim() + key);//将输入的数字显示
            // 如果文本框是0,则初始化变量,避免"00000”"这种情况出现
            if (this.tf.getText().equals("0")) {
                this.tf.setText("0");
                this.firstNum = true;
            }
        }
    }
    public void setDot(){
        if (this.tf.getText().indexOf(".") < 0) { //判断之前的输入是否存在“."
            this.firstNum = false;//设置不是第一个运算数
            this.tf.setText(this.tf.getText()+ ".");//将 ","”添加到结果之后
        }
    }
    public void setC(){
        this.tf.setText("0");
        this.firstNum = true;
        this.operator = "=";
    }
    public void setBackspace() {
        String text = this.tf.getText();
        int i = text.length();
        if (i > 0) {//如果文本框中有数据
            text = text.substring(0, i - 1);//将字符串中的最后一个字符消掉
            if (text.length() == 0) {//如果退格后已经没有数据了,则初始化全部成员变量
                this.tf.setText("0");
                this.firstNum = true;
                this.operator = "=";
            } else {//如果退格之后还有数据,则在文本框中显示剩余的数据
                this.tf.setText(text);
            }
        }
    }
    public double getNumber() {
        double result = 0.0;
        //将String类型转换为Double类型,再利用自动拆箱的功能将Double转换为double
        result = Double.valueOf(this.tf.getText());
        return result;
    }
    public String changeNum(double r) {
        long numA = (long) r;//取得结果的整数部分赋值给numA
        double numB = 0.0;
        numB = r - numA;//取得结果的小数部分赋值给numB
        if (numB == 0) {//如果小数部分为0
            return String.valueOf(numA);//只输出结果的整数部分
        } else {
            return String.valueOf(r);//输出结果本身
        }
    }
}